package com.example.springboottest.example.garbledcode;

import java.io.UnsupportedEncodingException;
import java.nio.charset.StandardCharsets;

/**
 * 乱码恢复
 * unicode只是规定了世界上所有字符的编码，但没有规定每个字符在各自编码下的二进制如何对应
 */
public class GarbledCode {
    public static void main(String[] args) {
        try {
            //方的unicode码是26041
            String unicode方 = "方";
            System.out.println(new Integer(unicode方.charAt(0)));

            //首先得到在gbk编码下的 方 是如何保存为对应的字节数组
            byte[] gbkByte方 = unicode方.getBytes("gbk");
            System.out.println("方在gbk编码下的二进制：" + gbkByte方);

            //得到在utf-8编码下的 方 是如何保存为对应的字节数组
            byte[] utf8Byte方 = unicode方.getBytes(StandardCharsets.UTF_8);
            System.out.println("方在utf-8编码下的二进制：" + utf8Byte方);

            //分别用gbk和utf-8进行解码
            String gbk方 = new String(gbkByte方, "gbk");
            String utf8方 = new String(utf8Byte方, StandardCharsets.UTF_8);
            System.out.println("gbkByte方在gbk解码还原：" + gbk方);
            System.out.println("utf8Byte方在utf-8解码还原：" + utf8方);


        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    //char 转 byte[] 数组
    public static byte[] charToByte(char c) {
        byte[] b = new byte[2];
        b[0] = (byte) ((c & 0xFF00) >> 8);
        b[1] = (byte) (c & 0xFF);
        return b;
    }

    //byte[] 数组转 char
    public static char byteToChar(byte[] b) {
        char c = (char) (((b[0] & 0xFF) << 8) | (b[1] & 0xFF));
        return c;
    }

    public static String UnicodeByteToStr(byte[] bBuf) {
//        return new String(bBuf, StandardCharsets.UTF_16LE); // 这种不会处理字符串结束符 \0
        StringBuffer result = new StringBuffer();
        Character ch = 0;
        for (int i = 0; i < bBuf.length; i += 2) {
            if (bBuf[i + 1] == 0) {
                ch = (char) bBuf[i];
            } else {
                ch = (char) ((bBuf[i] << 8) & 0xFF00 | bBuf[i + 1]);
            }

            if (ch == 0) { // 字符串结束符 \0
                break;
            }
            result.append(ch);
        }
        return result.toString();
    }

    /**
     * 恢复是需要多次尝试的，"windows-1252", "GB18030", "Big5", "UTF-8" 为常见编码，还可以添加
     *
     * @param str
     * @throws UnsupportedEncodingException
     */
    public static void recover(String str)
            throws UnsupportedEncodingException {
        String[] charsets = new String[]{
                "windows-1252", "GB18030", "Big5", "UTF-8"};
        for (int i = 0; i < charsets.length; i++) {
            for (int j = 0; j < charsets.length; j++) {
                if (i != j) {
                    String s = new String(str.getBytes(charsets[i]), charsets[j]);
                    System.out.println("---- 原来编码（A）假设是: "
                            + charsets[j] + ",被错误解读为了(B): " + charsets[i]);
                    System.out.println(s);
                    System.out.println();
                }
            }
        }
    }
}
